package com.hll.spring_book.aop;

import com.alibaba.fastjson.JSON;
import com.hll.spring_book.annotion.loginAnno;
import com.hll.spring_book.util.CommonResult;
import com.hll.spring_book.util.Constants;
import com.hll.spring_book.util.SessionHelper;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;

/**
 * @author: Mr.Hu
 * @create: 2021-03-30 11:00
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
  /*拦截器，实现登入拦截，调用接口必须给header附带上token属性，服务器验证才能通过*/

  // 返回未登入消息
  private static void printJson(HttpServletResponse response) {
    CommonResult responseResult = new CommonResult(Constants.NOT_LOGIN, "未登录", null);
    String content = JSON.toJSONString(responseResult);
    printContent(response, content);
  }

  // 打印消息工具方法
  private static void printContent(HttpServletResponse response, String content) {
    try {
      response.reset();
      response.setContentType("application/json");
      response.setHeader("Cache-Control", "no-store");
      response.setCharacterEncoding("UTF-8");
      PrintWriter pw = response.getWriter();
      pw.write(content);
      pw.flush();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  // 请求预处理，调用controller之前进入
  @Override
  public boolean preHandle(
      HttpServletRequest request, HttpServletResponse response, Object handler) {
    // 获取header-token,见相应vue工程的main.js设置
    String token = request.getHeader("token");
    // 如果不是映射到方法直接通过
    if (!(handler instanceof HandlerMethod)) {
      return true;
    }

    if (request.getRemoteHost().equals("0:0:0:0:0:0:0:1")) return true;

    // ！！！ 遇到了一个问题：如果打包成war包运行后，这部分取不到getToken(),但在login那里的确setToken了，待解决
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Method method = handlerMethod.getMethod();
    // 判断接口是否需要登录，如果有这个注解，代表不需要验证
    loginAnno methodAnnotation = method.getAnnotation(loginAnno.class);
    // 如果没有token，或者token与session中的不相等，那么视为未登入状态
    if (methodAnnotation != null) return true;
    else if (token == null
        || SessionHelper.getToken() == null
        || !token.equals(SessionHelper.getToken())) {
      request.getSession().removeAttribute(Constants.USER);
      printJson(response); // 打印结果
      return false; // 不执行controller
    } else return true;
  }
}
